<script>
import { defineComponent, computed, watch, ref } from 'vue';
import { createNamespace, getInputValue, getSystemInfo, transformStyleSize } from '../utils';

const { env: runEnv } = getSystemInfo();
export default defineComponent({
  name: createNamespace('InputGrid')[0],
  options: {
    // https://uniapp.dcloud.io/matter.html#mp
    virtualHost: true,
  },
  emits: ['update:modelValue', 'input'],
  props: {
    modelValue: {
      type: [String, Number],
      default: '',
    },
    // 输入内容长度
    length: {
      type: [String, Number],
      default: 6,
    },
    type: {
      type: String,
      default: 'text',
      validator: (value) => {
        return ['text', 'number', 'idcard', 'tel'].includes(value);
      },
    },
    gridStyle: String,
    cursorColor: {
      type: String,
      default: '#1677FE',
    },
    // 输入完成时是否自动收起软键盘
    autoBlur: {
      type: Boolean,
      default: true,
    },
  },
  setup(props, { emit }) {
    const innerValue = ref('');
    const focus = ref(false);
    const domRef = ref(null);

    const renderValues = computed(() => {
      const val = `${typeof innerValue.value === 'undefined' ? '' : innerValue.value
        }`;
      const length = props.length;
      let index = -1;
      const chars = Array.from({ length }).map((_, i) => {
        const char = val[i] || '';
        if (char === '' && index === -1) index = i;
        return char;
      });
      // 使光标停在最后一位
      if (val.length >= length) index = length - 1;
      return { chars, index };
    });
    const theStyle = computed(() => {
      return `--fan-grid-cursor-color:${props.cursorColor};`;
    });
    const gridInnerStyle = computed(() => transformStyleSize(props.gridStyle))

    watch(
      () => props.modelValue,
      (val) => {
        if (val !== innerValue.value) innerValue.value = val;
      },
      { immediate: true },
    );
    watch(
      innerValue,
      (val) => {
        if (val !== props.modelValue) emit('update:modelValue', val);
        emit('input', val);
      },
      { immediate: true },
    );

    const onFocus = () => {
      focus.value = true;
    };
    const onBlur = () => {
      focus.value = false;
    };

    const onInput = (e) => {
      const { length, type, autoBlur } = props;
      const innerValues = getInputValue(e);
      let val = String(innerValues);
      // 输入完成自动收起软键盘
      if (autoBlur && val.length >= length) {
        if (runEnv === 'h5') domRef.value.input.blur();
        onBlur();
      }
      if (val.length > length) val = val.substring(0, length);
      // TODO type=number时科学计数e作为第1个字符输入时异常
      if (val && (type === 'number' || type === 'tel')) {
        val = isNaN(+val) ? '' : +val;
      }
      if (val !== innerValue.value) innerValue.value = val;
    };
    const boxClick = () => {
      if (runEnv === 'h5') domRef.value.input.focus();
      if (!focus.value) focus.value = true;
      else focus.value = focus.value === 1 ? true : 1;
    };

    return {
      theStyle,
      gridInnerStyle,
      renderValues,
      innerValue,
      focus,
      onFocus,
      onBlur,
      onInput,
      boxClick,
    };
  },
});
</script>

<template>
  <div class="fan-grid-input" :style="theStyle">
    <input ref="input" class="fan-grid-input__in" :type="type" :value="innerValue" :focus="focus" :autofocus="focus"
      @focus="onFocus" @blur="onBlur" @input="onInput" />
    <div class="fan-flex" @click="boxClick">
      <div v-for="(char, index) in renderValues.chars" :key="index" class="fan-grid-input__box"
        :class="{ cursor: focus && index === renderValues.index }" :style="gridInnerStyle">
        {{ char }}
      </div>
    </div>
  </div>
</template>

<style lang="less">
.fan-grid-input {
  position: relative;

  &__in {
    color: transparent;
    opacity: 0;
    position: absolute;
    // z-index: -9;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
  }

  &__box {
    width: 32px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-left: 8px;
    border: 1px solid #84878f;
    border-radius: 4px;

    &:first-child {
      margin-left: 0;
    }

    &.cursor {
      &::after {
        content: '';
        display: block;
        width: 1px;
        height: 50%;
        background: var(--fan-grid-cursor-color);
        animation: fanCursorFlicker 1s infinite;
      }
    }
  }
}

@keyframes fanCursorFlicker {
  0% {
    opacity: 1;
  }

  40% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}
</style>
